package org.chen.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import org.chen.common.annotation.MasterRoute;
import org.chen.common.constants.Constants;
import org.chen.common.exception.FlyingException;
import org.chen.common.model.travel.StoreTravelOrder;
import org.chen.common.utils.RedisUtil;
import org.chen.enu.CancelResult;
import org.chen.service.OrderTaskService;
import org.chen.service.StoreTravelOrderService;
import org.chen.service.StoreTravelOrderTaskService;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
public class OrderTaskServiceImpl implements OrderTaskService {

    //日志
    private static final Logger logger = LoggerFactory.getLogger(OrderTaskServiceImpl.class);

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private StoreTravelOrderTaskService storeTravelOrderTaskService;

    @Autowired
    private StoreTravelOrderService storeTravelOrderService;

    @Autowired
    private RedissonClient redisson;

    /**
     * 自动取消未支付订单
     */
    @Override
    public void autoCancelTravel() {
        String redisKey = "order_cancel_delay";
        long now = System.currentTimeMillis();
        // 只获取已到期的订单（score <= now）
        Set<String> expiredOrders = redisUtil.zRangeByScore(redisKey, 0, now);

        if (CollUtil.isEmpty(expiredOrders)) {
            logger.info("没有到期的订单需要取消");
            return;
        }

        logger.info("扫描到 {} 个到期订单", expiredOrders.size());

        // 限制每次处理数量（防止长时间阻塞）
        int batchSize = Math.min(expiredOrders.size(), 100);
        int successCount = 0;
        int failCount = 0;

        for (String orderNo : expiredOrders) {
            if (successCount + failCount >= batchSize) break;

            RLock lock = redisson.getLock("cancel_order_lock:" + orderNo);
            try {
                if (!lock.tryLock(3, TimeUnit.SECONDS)) {
                    continue;
                }

                StoreTravelOrder order = storeTravelOrderService.getByOderId(orderNo);
                if (order == null) {
                    redisUtil.zRem(redisKey, orderNo);
                    continue;
                }

                CancelResult result = storeTravelOrderTaskService.autoCancel(order);

                switch (result) {
                    case SUCCESS:
                    case ALREADY_CANCELLED:
                    case ALREADY_PAID:
                        redisUtil.zRem(redisKey, orderNo);
                        redisUtil.delete("order_cancel_retry:" + orderNo);
                        successCount++;
                        break;

                    case PAYMENT_IN_PROGRESS:
                        // 延迟10分钟
                        redisUtil.zAdd(redisKey, orderNo, now + 10 * 60 * 1000);
                        break;

                    case SYSTEM_ERROR:
                        handleSystemError(redisKey, orderNo);
                        failCount++;
                        break;

                    default:
                        break;
                }
            } catch (Exception e) {
                logger.error("取消订单异常，orderNo: {}", orderNo, e);
                handleSystemError(redisKey, orderNo);
                failCount++;
            } finally {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
        }

        logger.info("订单取消完成，成功: {}, 失败: {}", successCount, failCount);
    }

    private void handleSystemError(String redisKey, String orderNo) {
        String retryKey = "order_cancel_retry:" + orderNo;
        Long retryCount = redisUtil.hIncr(retryKey, "count", 1);

        if (retryCount > 3) {
            // 移入人工处理队列
            redisUtil.lPush("order_manual_process", orderNo);
            redisUtil.zRem(redisKey, orderNo);
            redisUtil.delete(retryKey);

            logger.error("订单取消失败超过3次，已移入人工处理队列，orderNo: {}", orderNo);
            // TODO: 发送告警 邮件
        } else {
            // 延迟5分钟重试
            long retryTime = System.currentTimeMillis() + 5 * 60 * 1000;
            redisUtil.zAdd(redisKey, orderNo, retryTime);
            redisUtil.expire(retryKey, 3600, TimeUnit.SECONDS);
        }
    }

    /**
     * 用户取消订单
     */
    @Override
    public void cancelByUserTravel(Long id) {
        try {
            StoreTravelOrder storeOrder = storeTravelOrderService.getById(id);
            boolean result = storeTravelOrderTaskService.cancelByUser(storeOrder);
            if (!result) {
                logger.error("用户取消订单后置处理错误：result = " + false);
            }
        } catch (Exception e) {
            logger.error("用户取消订单后置处理错误：" + e.getMessage());
        }
    }

    /**
     * 完成订单(旅游)
     */
    @Override
    public void completeTravel(Long id) {
        try {
            StoreTravelOrder storeOrder = storeTravelOrderService.getById(id);
            boolean result = storeTravelOrderTaskService.complete(storeOrder);
            if (!result) {
                logger.error("完成订单后置处理错误：result = " + false);
            }
        } catch (Exception e) {
            logger.error("完成订单后置处理错误：" + e.getMessage());
        }
    }

    /**
     * 订单支付成功后置处理
     */
    @Override
    @MasterRoute
    public void orderPaySuccessAfterTravel(Long id) {
        try {
            StoreTravelOrder storeOrder = storeTravelOrderService.getById(id);
            if (ObjectUtil.isNull(storeOrder)) {
                logger.error("OrderTaskServiceImpl.orderPaySuccessAfterTravel | 订单不存在，orderId: " + id);
                throw new FlyingException("订单不存在，orderNo: " + id);
            }
            boolean result = storeTravelOrderTaskService.paySuccess(storeOrder);
            if (!result) {
                logger.error("订单支付成功后置处理错误：result = " + false);
            }
        } catch (Exception e) {
            logger.error("订单支付成功后置处理错误：" + e.getMessage());
        }
    }

    /**
     * 执行 用户退款申请
     * @author Mr.Zhang
     * @since 2020-07-09
     */
    @Override
    public void refundApply(Long id) {
        try {
            StoreTravelOrder storeOrder = storeTravelOrderService.getById(id);
            if (ObjectUtil.isNull(storeOrder)) {
                throw new FlyingException("订单不存在,orderId = " + id);
            }
            boolean result = storeTravelOrderTaskService.refundOrder(storeOrder);
            if (!result) {
                logger.error("订单退款错误：result = " + false);
            }
        } catch (Exception e) {
            logger.error("订单退款错误：" + e);
        }
    }

    /**
     * 执行 用户取消订单的退款申请
     */
    @Override
    public void refundCancelApply(StoreTravelOrder storeOrder) {
        try {
            if (ObjectUtil.isNull(storeOrder)) {
                throw new FlyingException("订单不存在,orderId");
            }
            boolean result = storeTravelOrderTaskService.refundOrder(storeOrder);
            if (!result) {
                logger.error("订单退款错误：result = " + false);
            }
        } catch (Exception e) {
            logger.error("订单退款错误：" + e);
        }
    }

    /**
     * 生成支付链接后续步骤*
     * @param id 订单id
     */
    @Override
    @MasterRoute
    public void generatePayMenteLink(Long id) {
        try {
            StoreTravelOrder storeOrder = storeTravelOrderService.getById(id);
            boolean result = storeTravelOrderTaskService.generatePayMenteLinkSuccess(storeOrder);
            if (!result) {
                logger.error("生成支付链接后续步骤错误：result = " + false);
            }
        } catch (Exception e) {
            logger.error("生成支付链接后续步骤错误：" + e.getMessage());
        }
    }
}
